﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace eBook.Core
{
  public class ISBN13 : ISBN
  {  
	  private Regex _isbn13exp = new Regex(@"^\d{13}$");

    #region Constructors 

    public ISBN13( string isbnValue ) : base( isbnValue )      
    {

    }   

    #endregion
    
    #region Overrides 

    public override bool Validate()
    {
      if ( this.ValidationError != ISBNValidationError.NotYetValidated )
        return this.ValidationError == ISBNValidationError.None;

      if ( _strippedISBN.Length != 13 )
      {
        this.ValidationError = ISBNValidationError.InvalidInputSize;
        return false;
      }

      if ( !( _isbn13exp.IsMatch( _strippedISBN ) ) )
      {
        this.ValidationError = ISBNValidationError.InvalidCharacters;
        return false;
      }

      #region Validation logic 
      
      int total = 0;
      int y = 0;
      for ( int x = 0; x < 12; x++ )
      {
        y = x % 2 == 0 ? 1 : 3;
        total += y * CharToDigitValue( _strippedISBN[x] );
      }

      // check digit
      char checkDigit = _strippedISBN[12];
      int z = CharToDigitValue( checkDigit );

      bool result = ( 10 - ( total % 10 ) ) % 10 == z; 
      
      #endregion
      
      if ( result )
        this.ValidationError = ISBNValidationError.None;
      else
        this.ValidationError = ISBNValidationError.CheckDigitError;

      return result;
    }

    public override string Hyphenate()
    {
      if ( !this.Validate() )
        return string.Format( "ERROR ({0})", this.ValidationError );

      return new ISBNHyphenator().HyphenateISBN13( _strippedISBN );
    }

    public override string Transform()
    {			
			if ( string.IsNullOrEmpty(_strippedISBN) )
				return _isbnval;	
							
			// a 13-digit ISBN has to begin with 978 in order to be converted to a 10-digit ISBN
			if (_strippedISBN.Substring(0,3) != "978") 
				return _isbnval;	
				
			string isbnnum = _strippedISBN.Substring(3,10);		
			int total = 0;

			for (int x = 0; x < 9; x++) 
				total += CharToDigitValue( isbnnum[x] ) * ( 10 - x );
			
			int z = (11 - (total % 11)) % 11;
			char checkDigit = z == 10 ? 'X' : Convert.ToChar(z.ToString()); 

			return isbnnum + z.ToString();
    }

    #endregion
  }
}
